/**
 * 棋盘画布配置
 */
// 棋盘配置
const gridSize = 50; // 格子大小
const boardSize = 15; // 棋盘网格数

/**
 * 画布未偏移前的棋子落点偏差
 */
const CanvasNormalPosition = {
    y: 8,
    x: 384
};

/**
 * 落子有效点击范围
 */
const playRadius = 20;


// 绘制棋盘
function drawChessboard(boardSize, gridSize) {
    let board = document.getElementById("board");
    if (board.hasChildNodes()) {
        board.removeChild(board.childNodes[0]);
    }
    const canvas = document.createElement("canvas");
    canvas.id = 'chessboardCanvas';
    window.chessboardCanvas = canvas;
    // 动态调节棋盘大小
    canvas.width = gridSize * boardSize + (2 * gridSize);
    canvas.height = gridSize * boardSize + (2 * gridSize);
    board.appendChild(canvas);
    drawChessboardLine(canvas, boardSize, gridSize);
    addCanvasListeners(canvas, boardSize, gridSize, playRadius);
}

/**
 * 棋盘线条
 */
function drawChessboardLine(canvas, boardSize, gridSize) {
    const ctx = canvas.getContext("2d");
    ctx.strokeStyle = "white";
    ctx.lineWidth = 1; // 线条宽度
    for (let i = 0; i < boardSize; i++) {
        // 水平线
        ctx.beginPath();
        let startX = gridSize
        let startY = (i + 1) * gridSize;
        let endX = gridSize * boardSize
        let endY = startY;
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
        // 垂直线
        ctx.beginPath();
        startX = gridSize + i * gridSize;
        startY = gridSize;
        endX = startX;
        endY = gridSize * boardSize;
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
    }
}

function chessDeviationPosition(canvas) {
    let nx = CanvasNormalPosition.x;
    let ny = CanvasNormalPosition.y;
    let rect = canvas.getBoundingClientRect();
    // x 的偏差
    let deviationX = Math.floor(Math.abs(rect.x - nx));
    // y 的偏差
    let deviationY = Math.floor(Math.abs(rect.y - ny));
    return {
        x: deviationX,
        y: deviationY
    }
}

function chessDeviationPositionValue(value, deviation) {
    if (value < 0) {
        return value - deviation;
    } else {
        return value + deviation;
    }
}

function addCanvasListeners(canvas, boardSize, gridSize, playRadius) {
    canvas.addEventListener("click", function (event) {
        if (winning) {
            return;
        }
        const rect = canvas.getBoundingClientRect();
        let x = event.clientX - Math.floor(rect.x);
        let y = event.clientY - Math.floor(rect.y);
        let chessPosition = calculatePlayChessPosition(x, y, boardSize, gridSize, playRadius);
        if (null == chessPosition) {
            console.error('落子位置无效', x, y);
            return;
        }
        let role = selfTurn ? 1 : 2;
        let success = ChessBoardData_playChess(chessPosition.xIndex, chessPosition.yIndex, role);
        if (!success) {
            return;
        }
        let chessData = {color: ChessBoardData.blackChessColor};
        if (role === 1) {
            chessData.color = ChessBoardData.blackChessColor;
        } else if (role === 2) {
            chessData.color = ChessBoardData.whiteChessColor;
        }
        drawChess(canvas, chessPosition, chessData);
        selfTurn = !selfTurn;
        if (isWin(0,0, role)) {
            let winner = role === 1 ? '黑棋' : '白棋';
            popUpMessageShow(`恭喜${winner}胜利`);
            winning = true;
        }
    });
    canvas.addEventListener("mousemove", function (event) {
        const rect = canvas.getBoundingClientRect();
        let x = event.clientX - Math.floor(rect.left);
        let y = event.clientY - Math.floor(rect.top);
        const col = Math.floor(x / gridSize);
        const row = Math.floor(y / gridSize);
        let chessPosition = calculatePlayChessPosition(x, y, boardSize, gridSize, playRadius);
        if (null == chessPosition) {
            hideChessHover();
            return;
        }
        let data = ChessBoardData_getData();
        if (chessPosition.xIndex < 0 || chessPosition.yIndex < 0 || chessPosition.xIndex >= data.length || chessPosition.yIndex >= data[0].length) {
            hideChessHover();
            return;
        }
        if (data[chessPosition.xIndex][chessPosition.yIndex].color !== 0) {
            hideChessHover();
            return;
        }
        hideChessHover();
        showChessHover(canvas, chessPosition);
    });
    return canvas;
}

// 展示悬停内容的函数
function showChessHover(chessboardCanvas, chessPosition) {
    if (winning) {
        return;
    }
    let hoverPosition = document.getElementById('play-chess-hover');
    hoverPosition.classList.add('show');
    const rect = chessboardCanvas.getBoundingClientRect();
    let canvasDistanceX = Math.floor(rect.x);
    let canvasDistanceY = Math.floor(rect.y);
    const centerX = chessPosition.chessDrawX + canvasDistanceX;
    const centerY = chessPosition.chessDrawY + canvasDistanceY;
    let hoverPositionSize = parseInt(
        window.getComputedStyle(hoverPosition).getPropertyValue('width')
    );
    let hoverPositionRadius = Math.floor(hoverPositionSize / 2);
    let deviationPosition = chessDeviationPosition(chessboardCanvas);
    let top = chessDeviationPositionValue(centerY - hoverPositionRadius, deviationPosition.y);
    let left = chessDeviationPositionValue(centerX - hoverPositionRadius, deviationPosition.x);
    hoverPosition.style.top = `${top}px`;
    hoverPosition.style.left = `${left}px`;

}

// 隐藏悬停内容的函数
function hideChessHover() {
    let hover = document.getElementById('play-chess-hover');
    hover.classList.remove('show');
}

/**
 * 计算落子位置
 * @param x 点击的x坐标
 * @param y 点击的y坐标
 * @param boardSize 棋盘规格，横或竖能落多少子（矩形）
 * @param gridSize 棋盘中每个格子大小
 * @param playRadius 每个落子位置的有效识别范围（矩形）
 * @return chessPosition 返回一个对象，里面包含落子位置，以及对应棋盘数据（二维数组）的下标，如果落子无效则返回 null
 */
function calculatePlayChessPosition(x, y, boardSize, gridSize, playRadius) {
    let xg = Math.floor(x / gridSize);
    let yg = Math.floor(y / gridSize);
    // 落子x
    let playX = (xg > 0 ? xg : 1) * gridSize;
    // 落子y
    let playY = (yg > 0 ? yg : 1) * gridSize;
    let xr = Math.abs(x - playX) <= playRadius;
    let yr = Math.abs(y - playY) <= playRadius;
    // x 落点不符合有效范围，则往右进一查看范围
    if (!xr) {
        playX = (xg + 1) * gridSize;
        xr = Math.abs(x - playX) <= playRadius;
    }
    // y 落点不符合有效范围，则往下进一查看范围
    if (!yr) {
        playY = (yg + 1) * gridSize;
        yr = Math.abs(y - playY) <= playRadius;
    }
    if (!xr || !yr) {
        return null;
    }
    let rxi = (playX / gridSize) - 1;
    let ryi = (playY / gridSize) - 1;
    if (rxi >= boardSize || ryi >= boardSize || rxi < 0 || ryi < 0) {
        return null;
    }
    return {
        xIndex: rxi,
        yIndex: ryi,
        chessDrawX: playX,
        chessDrawY: playY
    }
}

/**
 *
 * @param chessboardCanvas
 * @param chessPosition \{chessDrawX: 画布的x坐标, chessDrawY: 画布的y坐标}
 * @param chessData
 * @param isFill 是否为填充方式显示棋子，填充形式不考虑屏幕偏差
 */
function drawChess(chessboardCanvas, chessPosition = {
    chessDrawX: 0,
    chessDrawY: 0
}, chessData = {color: ChessBoardData.blackChessColor}, isFill = false) {
    drawChessWithCSS(chessboardCanvas, chessPosition, chessData, isFill);
}

function drawChessWithCSS(chessboardCanvas, chessPosition = {
    chessDrawX: 0,
    chessDrawY: 0
}, chessData = {color: ChessBoardData.blackChessColor}, isFill = false) {
    // 为了防止屏幕因滚动条下划而产生落子坐标偏差，需要减去滚动条距离
    let deviation = chessDeviationPosition(chessboardCanvas);
    // 在生成好的棋子坐标基础上进行二次校准
    let x = chessPosition.chessDrawX;
    let y = chessPosition.chessDrawY;
    // 先把隐形的chessDiv添加到DOM树中，才可以自动获取CSS里面的属性
    let chessDiv = document.createElement('div');
    chessDiv.className = `chessBox chessBox-${chessData.color}`;
    const rect = chessboardCanvas.getBoundingClientRect();
    let canvasDistanceX = Math.floor(rect.x);
    let canvasDistanceY = Math.floor(rect.y);
    if (isFill) {
        canvasDistanceX = Math.floor(CanvasNormalPosition.x);
        canvasDistanceY = Math.floor(CanvasNormalPosition.y);
        deviation = {x: 0, y: 0};
    }
    document.getElementById('chessboardCSS').appendChild(chessDiv);
    const centerX = x + canvasDistanceX;
    const centerY = y + canvasDistanceY;
    // 棋子样式在chessbox.css的.chessBox
    let chessBoxSize = parseInt(
        window.getComputedStyle(chessDiv).getPropertyValue('width')
    );
    let chessBoxRadius = Math.floor(chessBoxSize / 2);
    let left = chessDeviationPositionValue(centerX - chessBoxRadius, deviation.x);
    let top = chessDeviationPositionValue(centerY - chessBoxRadius, deviation.y);
    chessDiv.style.top = `${top}px`;
    chessDiv.style.left = `${left}px`;
}

function resetChessboard() {
    resetChessboardWithCSS();
}

function resetChessboardWithCSS() {
    let board = document.getElementById('chessboardCSS');
    board.innerHTML = '';
}

function fillChess(chess) {
    if (chess.length > boardSize || chess[0].length > boardSize) {
        console.error('棋盘数据长度错误');
        return;
    }
    let chessboardData = ChessBoardData_getData();
    for (let i = 0; i < chess.length; i++) {
        for (let j = 0; j < chess[i].length; j++) {
            if (chess[i][j] === 0) {
                continue;
            }
            let chessData = {
                color: ChessBoardData.blackChessColor,
            }
            if (chess[i][j] === 1) {
                chessData.color = ChessBoardData.blackChessColor;
            } else if (chess[i][j] === 2) {
                chessData.color = ChessBoardData.whiteChessColor;
            }
            let c = chessboardData[i][j];
            let chessPosition = {
                chessDrawX: c.drawX,
                chessDrawY: c.drawY,
            }
            drawChess(window.chessboardCanvas, chessPosition, chessData, true);
        }
    }
}

function isWin(xIndex = 0, yIndex = 0, color) {
    return checkWin(ChessBoardData_getData(), color);
}

function checkWin(board, player) {
    const directions = [
        [1, 0],  // 水平方向
        [0, 1],  // 垂直方向
        [1, 1],  // 对角线方向（左上到右下）
        [1, -1]  // 对角线方向（右上到左下）
    ];

    for (let row = 0; row < board.length; row++) {
        for (let col = 0; col < board[row].length; col++) {
            if (board[row][col].color === player) {
                for (let [dr, dc] of directions) {
                    let count = 1;
                    for (let step = 1; step < 5; step++) {
                        const newRow = row + dr * step;
                        const newCol = col + dc * step;
                        if (newRow >= 0 && newRow < board.length &&
                            newCol >= 0 && newCol < board[row].length &&
                            board[newRow][newCol].color === player) {
                            count++;
                        } else {
                            break;
                        }
                    }
                    if (count === 5) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
